package one.stand.eureka.info;

import lombok.Builder;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.maven.model.Model;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.yaml.snakeyaml.Yaml;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

@Slf4j
public class ServiceConfigReader {
    private Yaml yaml = new Yaml();
    private CommandExecuter commandExecuter = new CommandExecuter();
    private Config config;

    private String deploy;

    public ServiceConfigReader(String deploy) {
        this.deploy = deploy;
    }

    public String getLastVersion(String name) {
        String projectPath = config.getServices().get(name).getPath();
        if (StringUtils.isBlank(projectPath)) {
            return StringUtils.EMPTY;
        }

        String pomfile = config.getProjectBootPath() + File.separator + projectPath + File.separator + "pom.xml";

        FileInputStream fis = null;
        Model model = null;
        try {
            fis = new FileInputStream(new File(pomfile));
            MavenXpp3Reader reader = new MavenXpp3Reader();
            model = reader.read(fis);
            return model.getVersion();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (Objects.nonNull(fis)) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return StringUtils.EMPTY;
    }

    public Collection<ServiceConfig> get() {
        return config.getServices().values();
    }

    public Map<String, String> getCommands(String name) {
        return config.getServices().get(name).getConfig();
    }

    public String getCommand(String name, String commandKey) {
        Map<String, String> commonds = config.getServices().get(name).getConfig();
        return commonds.get(commandKey);
    }

    public void reload() {
        if (Objects.isNull(config)) {
            load();
        }

        commandExecuter.exe(config.getCdBootPath(), null);

        load();
    }

    private void load() {
        InputStream inputStream = null;
        File file = new File(deploy);
        try {
            inputStream = new FileInputStream(file);
            Map<String, Object> ret = (Map<String, Object>) yaml.load(inputStream);
            config = Config.builder()
                    .cdBootPath((String) ret.get("cdBootPath"))
                    .projectBootPath((String) ret.get("projectBootPath"))
                    .services(new LinkedHashMap<>())
                    .build();
            List<LinkedHashMap<String, Object>> services = (List<LinkedHashMap<String, Object>>) ret.get("services");
            for (LinkedHashMap<String, Object> map : services) {
                ServiceConfig serviceConfig = new ServiceConfig();
                serviceConfig.setName((String) map.get("name"));
                serviceConfig.setPath((String) map.get("path"));
                serviceConfig.setConfig((Map<String, String>) map.get("config"));
                config.getServices().put(serviceConfig.getName(), serviceConfig);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        } finally {
            try {
                if (Objects.nonNull(inputStream)) {
                    inputStream.close();
                }
            } catch (IOException e) {
                log.error(e.getMessage(), e);
            }
        }
        log.info("yml reload");
    }

    public boolean checkTure(String name) {
        return "Maven".equals(name);
    }

    @Data
    @Builder
    public static class Config {
        private String cdBootPath;
        private String projectBootPath;
        private Map<String, ServiceConfig> services;
    }

    @Data
    public static class ServiceConfig {
        private String name;
        private String path;
        private Map<String, String> config;
    }
}
